import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.io.*;
public class UdpServer2 {

    private static final int PORT = 8888;
    // 服务器socket要绑定 固定的端口
    // 本地文件目录要展示的根目录
    private static final String BASE_PATH = "D:\\";
    public static void main(String[] args) throws IOException {
        // 1. 创建服务端 DatagramSocket，指定端口，可以发送和接收UDP数据报
        DatagramSocket socket = new DatagramSocket(PORT);  // 也可以不指定端口号，如果不指定，那么会自动随机分配
        // 不停的接收客户端发送的数据
        while (true) {
            // 2. 创建数据报， 用于接收客户端发送的数据
            byte[] requestData = new byte[1024];  // upd报文的最大长度为 64k，包含udp首部 8 byte在内
            DatagramPacket requestPacket = new DatagramPacket(requestData, requestData.length);
            //   DatagramPacket 专门用来装 udp发送和接收的数据的
            System.out.println("---------------------------------------------------------------------");
            System.out.println("等待接收UDP数据报...");
            // 3.等待 客户端发送的udp数据报 ， 该方法在接收到数据报之前 会一直阻塞， 受到数据报之后DatagramPacket中的字段会被初始化赋值
            socket.receive(requestPacket);        // DatagramSocket 最常用的方法之一  另一个是send
            System.out.printf("客户端IP：%s%n", requestPacket.getAddress().getHostAddress());
            // getAddress 是获取DatagramPacket中 InetAddress对象 ，该对象中存储了 IP地址和端口号
            System.out.printf("客户端端口号：%s%n", requestPacket.getPort());

            // 7. 接收到的数据作为请求，根据 请求数据执行业务，并返回响应
            for (int i = 0; i < requestData.length; i++) {
                byte b = requestData[i];
                if(b == '\3'){ // 这里是约定结束符，读取数据时只取结束符之前的内容，多的内容丢弃
                    String request = new String(requestData,0 ,i);
                    // 根据请求粗合理 业务 ： 文帝目录根路径 + 请求路径，作为要展示的目录， 列出下一级自稳文件
                    // 请求的 文件列表目录
                    System.out.printf("客户端请求的文件列表路径为：%s%n",BASE_PATH+request);
                    File dir = new File(BASE_PATH+request);
                    // 获得下一级子文件，  子文件夹
                    File[] children = dir.listFiles();
                    // 构造要返回的响应内容：每个文件及目录名称为一行
                    StringBuilder response = new StringBuilder();
                    if(children != null){
                        for(File child : children){
                            response.append(child.getName()+"\n");
                        }
                    }
                    // 约定的结束符这时候加上
                    response.append("\3");
                    // 响应内容原本为 StringBuilder  ，先转为Sting类型之后，再通过getBytes转为字节数组类型
                    byte[] responseData = response.toString().getBytes(StandardCharsets.UTF_8);
                    // 构造返回响应的数据报    这里第三个参数原来应该是 InetAddress对象 存IP，端口号，这里因为之前接收过 UDP请求，所以可以直接从请求对象中获取
                    DatagramPacket responsePacket = new DatagramPacket(responseData, responseData.length, requestPacket.getSocketAddress());

                    // 发送返回响应的数据报
                    socket.send(responsePacket);
                    break;
                }
            }
            //System.out.printf("客户端发送的原生数据为：%s%n", Arrays.toString(packet.getData()));
            //System.out.printf("客户端发送的文本数据为：%s%n", new String(packet.getData()));
        }
    }
}
